/**
 * 
 */
package com.cmcc.awareness;

import java.util.Arrays;

import javax.xml.bind.DatatypeConverter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.pcap4j.packet.Packet;

/**
 * @author Amish
 * @date 2018年12月7日 下午7:13:19
 * 
 * 字符串操作符表达式：s
 * 
 *  eg1:
 *  [TCP]
	# 3131
	{s|2|0x20666574696f6e2e636f6d2e636e205349502d432f}
	#3132
	{s|3|0x20666574696f6e2e636f6d2e636e205349502d432f}
	
	eg2:
	[TCP]
	# 10841
	{s|4|TXWB}
 */
public class ProtoDatProtocolFeatureCodeElement_s implements ProtoDatProtocolFeatureCodeElement {
	private static Logger logger = LogManager.getLogger(ProtoDatProtocolFeatureCodeElement_s.class);

	String initialStr;
	
	String offset;
	String value;//如果有0x，并不去掉
	
	public String appName;
	public String protocolType;
	public ProtoDatProtocolFeatureCodeElement_s(String appName,String protocolType){
		this.appName = appName;
		this.protocolType = protocolType;
	}
	
	@Override
	public String getType() {
		return "s";
	}

	
	@Override
	public boolean distinguish(String protocolType,jpcap.packet.Packet packet) {
		try{
            byte[] data = packet.data;
			
			int offsetInt = Integer.valueOf(offset);
			if(data == null || data.length == 0 )
				return false;
				    
		    String dataValueStr;
		    byte[] dataValueByte;
		    if(offsetInt < 0){
		    	
		    	if(this.value.startsWith("0x")){
		    		if(data.length < Math.abs(offsetInt) || (value.length()/2-1) > Math.abs(offsetInt))//长度不满足要求直接返回fasle
				    	return false;
		    		
		    		dataValueByte = Arrays.copyOfRange(data, offsetInt + data.length, offsetInt + data.length + value.length()/2-1);//需减掉0x长度
		    		dataValueStr = "0x"+DatatypeConverter.printHexBinary(dataValueByte);//转换成16进制字符串
				}else{
					if(data.length < Math.abs(offsetInt) || value.length() > Math.abs(offsetInt))//长度不满足要求直接返回fasle
				    	return false;
					
					dataValueByte = Arrays.copyOfRange(data, offsetInt + data.length, offsetInt + data.length + value.length());
				    dataValueStr = new String(dataValueByte,"UTF-8");//TODO 可能是其他编码吗？
				}
		    	
		    }else{//offset>=0

		    	if(this.value.startsWith("0x")){
		    		if( data.length < (offsetInt + value.length()/2-1))//长度不满足要求直接返回fasle
		    			return false;
		    		
		    		dataValueByte = Arrays.copyOfRange(data, offsetInt, offsetInt + value.length()/2-1);//需减掉0x长度
		    		dataValueStr = "0x"+DatatypeConverter.printHexBinary(dataValueByte);//转换成16进制字符串
				}else{
					if(data.length < (offsetInt + value.length()))//长度不满足要求直接返回fasle
						return false;
					
					dataValueByte = Arrays.copyOfRange(data, offsetInt, offsetInt+value.length());
				    dataValueStr = new String(dataValueByte,"UTF-8");
				}
		    }
		    
		    if(dataValueStr.equals(value)){//区分大小写
		    	return true;
		    }
			
			return false;
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("Distinguish Exception -- <"+this.appName+">"+"<"+this.protocolType+"> : "+this.toString());
			return false;
		}
	}

	
	@Override
	public void parseSelf(String element) {
		try{			
			this.initialStr = element;
			String strs[] = element.split("\\|");
			this.offset = strs[1];
			this.value = strs[2];

		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public String toString(){
		return "{"+initialStr+"}";
	}

	@Override
	public boolean distinguish(String protocolType, Packet packet) {
		try{
            byte[] data = packet.getRawData();
			
			int offsetInt = Integer.valueOf(offset);
			if(data == null || data.length == 0 )
				return false;
				    
		    String dataValueStr;
		    byte[] dataValueByte;
		    if(offsetInt < 0){
		    	
		    	if(this.value.startsWith("0x")){
		    		if(data.length < Math.abs(offsetInt) || (value.length()/2-1) > Math.abs(offsetInt))//长度不满足要求直接返回fasle
				    	return false;
		    		
		    		dataValueByte = Arrays.copyOfRange(data, offsetInt + data.length, offsetInt + data.length + value.length()/2-1);//需减掉0x长度
		    		dataValueStr = "0x"+DatatypeConverter.printHexBinary(dataValueByte);//转换成16进制字符串
				}else{
					if(data.length < Math.abs(offsetInt) || value.length() > Math.abs(offsetInt))//长度不满足要求直接返回fasle
				    	return false;
					
					dataValueByte = Arrays.copyOfRange(data, offsetInt + data.length, offsetInt + data.length + value.length());
				    dataValueStr = new String(dataValueByte,"UTF-8");//TODO 可能是其他编码吗？
				}
		    	
		    }else{//offset>=0

		    	if(this.value.startsWith("0x")){
		    		if( data.length < (offsetInt + value.length()/2-1))//长度不满足要求直接返回fasle
		    			return false;
		    		
		    		dataValueByte = Arrays.copyOfRange(data, offsetInt, offsetInt + value.length()/2-1);//需减掉0x长度
		    		dataValueStr = "0x"+DatatypeConverter.printHexBinary(dataValueByte);//转换成16进制字符串
				}else{
					if(data.length < (offsetInt + value.length()))//长度不满足要求直接返回fasle
						return false;
					
					dataValueByte = Arrays.copyOfRange(data, offsetInt, offsetInt+value.length());
				    dataValueStr = new String(dataValueByte,"UTF-8");
				}
		    }
		    
		    if(dataValueStr.equals(value)){//区分大小写
		    	return true;
		    }
			
			return false;
		}catch(Exception e){
			e.printStackTrace();
			System.out.println("Distinguish Exception -- <"+this.appName+">"+"<"+this.protocolType+"> : "+this.toString());
			return false;
		}
	}

}
